﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnvDTE;
using System.Text.RegularExpressions;

namespace Addin665.Commands {
    /// <summary>
    /// 批量 get set
    /// </summary>
    class MultiGetSetCmd : CommandBase {
        public override string Name {
            get {
                return "MultiGetSetCmd";
            }
        }

        public override void OnClick() {
            base.OnClick();

            try {
                Document doc = base.ApplicationObject.ActiveDocument;
                if (doc == null) {
                    return;
                }
                TextDocument textObj = doc.Object("TextDocument") as TextDocument;
                EditPoint editPoint = textObj.CreateEditPoint();

                //string allText = editPoint.GetText(textObj.EndPoint);
                TextSelection textSelection = doc.Selection as TextSelection;
                ////查找起始行和终止行
                int startLineIdx = textSelection.TopLine;
                int endLineIdx = textSelection.BottomLine;
                ////获取选定行的代码
                StringBuilder sb = new StringBuilder();
                for (int i = startLineIdx; i <= endLineIdx; i++) {
                    textSelection.GotoLine(i, true);
                    ////去除注释
                    string clearCode = textSelection.Text.Trim();
                    if (string.IsNullOrEmpty(clearCode)) {
                        continue;
                    }
                    if (clearCode.StartsWith("//")) {
                        continue;
                    }
                    if (clearCode.StartsWith("/*")) {
                        continue;
                    }
                    if (clearCode.StartsWith("*")) {
                        continue;
                    }

                    Regex r = new Regex(";+ *//.*");
                    MatchCollection mc = r.Matches(clearCode);
                    if (mc.Count > 0) {
                        int idx = clearCode.IndexOf(mc[0].Value.Replace(";", ""));
                        clearCode = clearCode.Substring(0, idx);
                    }
                    sb.AppendLine(clearCode);
                }

                string appendStr = BreakTotalStr2Declare(sb);
                if (string.IsNullOrEmpty(appendStr)) {
                    return;
                }
                textSelection.MoveTo(endLineIdx, 0, false);
                textSelection.NewLine();
                textSelection.Insert(appendStr);
                int afterAppendLine = textSelection.ActivePoint.Line;
                ////void MoveTo(int Line, int Column, bool Extend = false);
                textSelection.MoveTo(startLineIdx, 0, true);
                textSelection.SmartFormat();
                //textSelection.MoveTo(afterAppendLine, 0, false);
            }
            catch (Exception ex) {

                throw;
            }
        }
        /// <summary>
        /// 一整段代码分配成若干声明语句 按 ; 分号
        /// </summary>
        /// <param name="totalStr"></param>
        string BreakTotalStr2Declare(StringBuilder totalStr) {
            StringBuilder ret = new StringBuilder();

            Regex r = new Regex("[^;]+;");
            MatchCollection mc = r.Matches(totalStr.ToString());
            for (int i = 0; i < mc.Count; i++) {
                string lineStr = mc[i].Value;
                lineStr = lineStr.Trim();
                lineStr = lineStr.TrimEnd(';');
                lineStr = lineStr.Replace(Environment.NewLine, "");
                ret.Append(this.BreakLine2Sentence(lineStr));
            }

            return ret.ToString();
        }
        /// <summary>
        /// 解析出声明的所有变量 按空格 和 逗号
        /// </summary>
        /// <param name="lineStr"></param>
        /// <returns></returns>
        private string BreakLine2Sentence(string lineStr) {
            StringBuilder ret = new StringBuilder();

            ////不含, 且 不含 =
            if (!lineStr.Contains(',') && !lineStr.Contains('=')) {
                Regex r = new Regex("[^ *]+");
                MatchCollection mc = r.Matches(lineStr);
                ////参数名称
                string proName = mc[mc.Count - 1].Value;
                ////参数类型
                string proType = mc[mc.Count - 2].Value;
                ret.Append(this.CreateCode(proType, proName));
            }
            ////包含, 不包含 =
            else if (lineStr.Contains(',') && !lineStr.Contains('=')) {
                Regex r = new Regex("[^,]+");
                MatchCollection mc = r.Matches(lineStr);
                ////
                r = new Regex("[^ *]+");
                MatchCollection fir = r.Matches(mc[0].Value);
                string proType = fir[0].Value;

                List<string> proNames = new List<string>();
                proNames.Add(fir[1].Value.Replace(",", ""));

                for (int i = 1; i < mc.Count; i++) {
                    proNames.Add(mc[i].Value.Replace(",", ""));
                }

                for (int i = 0; i < proNames.Count; i++) {
                    ret.Append(this.CreateCode(proType, proNames[i]));
                }
            }
            ////不含, 含 =
            else if (!lineStr.Contains(',') && lineStr.Contains('=')) {
                lineStr = lineStr.Split('=')[0].Trim();
                Regex r = new Regex("[^ *]+");
                MatchCollection mc = r.Matches(lineStr);
                ////参数名称
                string proName = mc[mc.Count - 1].Value;
                ////参数类型
                string proType = mc[mc.Count - 2].Value;
                ret.Append(this.CreateCode(proType, proName));
            }
            //// 含, 含 =
            else if (lineStr.Contains(',') && lineStr.Contains('=')) {
                Regex r = new Regex("[^,]+");
                MatchCollection mc = r.Matches(lineStr);

                r = new Regex("[^ *]+");
                MatchCollection firstPice = r.Matches(mc[0].Value);
                string proType = firstPice[0].Value;

                List<string> proNames = new List<string>();
                proNames.Add(firstPice[1].Value);

                for (int i = 1; i < mc.Count; i++) {
                    MatchCollection otherPice = r.Matches(mc[i].Value);
                    proNames.Add(otherPice[0].Value);
                }

                for (int i = 0; i < proNames.Count; i++) {
                    ret.Append(this.CreateCode(proType, proNames[i]));
                }
            }

            return ret.ToString();
        }
        /// <summary>
        /// 获取属性名称
        /// </summary>
        /// <param name="proName"></param>
        /// <returns></returns>
        string GetProName(string proName) {
            proName = proName.Trim();

            string ret = proName;
            if (proName.StartsWith("_")) {
                ret = proName.Substring(1, 1).ToUpper() + proName.Substring(2);
            }
            else {
                ret = proName.Substring(0, 1).ToUpper() + proName.Substring(1);
            }
            if (ret == proName) {
                ret = proName + "Property";
            }
            return ret;
        }
        /// <summary>
        /// 创建Get Set 代码
        /// </summary>
        /// <param name="proType"></param>
        /// <param name="proName"></param>
        /// <returns></returns>
        string CreateCode(string proType, string proName) {
            StringBuilder ret = new StringBuilder();
            string fullPath = System.Reflection.Assembly.GetAssembly(typeof(Connect)).Location;
            string tplFile = System.IO.Path.GetDirectoryName(fullPath) + @"\Data" + @"\MultiGetSetTpl.txt";
            if (System.IO.File.Exists(tplFile)) {
                ret.AppendLine(CommonHelp.FileHelper.ReadFile(tplFile));
                ret.Replace("$T", proType);
                ret.Replace("$_A", proName);
                ret.Replace("$A", this.GetProName(proName));

            }
            else {
                ret.AppendLine(CreateGetSetDefaultString(proType, proName));
            }
            return ret.ToString();
        }

        string CreateGetSetDefaultString(string proType, string proName) {
            StringBuilder ret = new StringBuilder();
            ret.AppendLine(@"public " + proType + " " + this.GetProName(proName) + "{");
            ////get
            ret.AppendLine("get{");
            ret.AppendLine("return " + proName + ";");
            ret.AppendLine("}");
            ////set
            ret.AppendLine("set{");
            ret.AppendLine(proName + " = value;");
            ret.AppendLine("}");

            ret.Append("}");
            return ret.ToString();
        }
    }
}
